package com.wnxy.filter;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wnxy.dto.LoginDto;
import com.wnxy.dto.ManagerDetail;
import com.wnxy.dto.StatusCode;
import com.wnxy.exception.LoginException;
import com.wnxy.model.Manager;
import com.wnxy.service.ManagerService;
import com.wnxy.service.impl.PhoneFailureHandler;
import com.wnxy.service.impl.PhoneSuccessHandler;
import com.wnxy.token.PhoneAuthenticationToken;
import com.wnxy.util.BeanCopyUtil;
import com.wnxy.util.CommonsUtil;
import com.wnxy.util.DateUtil;
import com.wnxy.util.GetRequestUtil;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.lang.Nullable;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.util.Assert;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class PhoneAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
    public static final String SPRING_SECURITY_FORM_PHONE_KEY = "phone";
    public static final String SPRING_SECURITY_FORM_CODE_KEY = "code";
    private static final AntPathRequestMatcher DEFAULT_ANT_PATH_REQUEST_MATCHER = new AntPathRequestMatcher("/phoneLogin", "POST");
    private String phoneParameter = "phone";
    private String codeParameter = "code";
    //    private boolean postOnly = true;
    private ManagerService managerService;
    private StringRedisTemplate srt;


    public PhoneAuthenticationFilter(ManagerService managerService, StringRedisTemplate srt,PhoneSuccessHandler psh,PhoneFailureHandler pfh) {
        super(DEFAULT_ANT_PATH_REQUEST_MATCHER);
        this.setAuthenticationSuccessHandler(psh);
        this.setAuthenticationFailureHandler(pfh);
        this.managerService = managerService;
        this.srt = srt;
    }

    public PhoneAuthenticationFilter(AuthenticationManager authenticationManager) {
        super(DEFAULT_ANT_PATH_REQUEST_MATCHER, authenticationManager);

    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
//        if (this.postOnly && !request.getMethod().equals("POST")) {
//            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
//        } else {
        String phone = this.obtainPhone(request);
        phone = phone != null ? phone : "";
        phone = phone.trim();
        String code = this.obtainPassword(request);
        code = code != null ? code : "";
        System.out.println(phone + " " + code);
//        if (!CommonsUtil.hasAllFields(loginByPhoneVo)) throw new LoginException(StatusCode.LOGINERROR.getCode(), "请填写完整信息");
        Manager manager = managerService.getOne(new QueryWrapper<Manager>().eq("manager_phone", phone));
        if (manager == null) throw new InternalAuthenticationServiceException("用户不存在");
        String s = srt.opsForValue().get("wnxy:theater:manager:" + phone);
        if (null == s) throw new InternalAuthenticationServiceException("验证码无效,请重新发送");
        if (!s.equals(code)) throw new InternalAuthenticationServiceException("验证码错误,请重新填写");

        PhoneAuthenticationToken authRequest = new PhoneAuthenticationToken(BeanCopyUtil.copyProperties(manager, ManagerDetail.class), null, null);
        this.setDetails(request, authRequest);
        return authRequest;
    }

    @Nullable
    protected String obtainPhone(HttpServletRequest request) {
        return request.getParameter(this.phoneParameter);
    }

    @Nullable
    protected String obtainPassword(HttpServletRequest request) {
        return request.getParameter(this.codeParameter);
    }

    protected void setDetails(HttpServletRequest request, PhoneAuthenticationToken authRequest) {
        authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
    }

    public void setUsernameParameter(String usernameParameter) {
        Assert.hasText(usernameParameter, "Username parameter must not be empty or null");
        this.phoneParameter = usernameParameter;
    }

    public void setPasswordParameter(String passwordParameter) {
        Assert.hasText(passwordParameter, "Password parameter must not be empty or null");
        this.codeParameter = passwordParameter;
    }

//    public void setPostOnly(boolean postOnly) {
//        this.postOnly = postOnly;
//    }

    public final String getUsernameParameter() {
        return this.phoneParameter;
    }

    public final String getPasswordParameter() {
        return this.codeParameter;
    }
}
